package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.module.common.iap.IapGift;
import com.motu.monstercity.module.common.servermanager.ServerInfo;
import com.motu.monstercity.module.common.servermanager.ServerManager;
import com.motu.monstercity.protocol.Common;
import com.motu.monstercity.protocol.CsGameUnionscuffle;
import com.motu.monstercity.server.game.base.AllParam;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.act.Act;
import com.motu.monstercity.server.game.commondata.bag.ItemId;
import com.motu.monstercity.server.game.commondata.mail.MailConstant;
import com.motu.monstercity.server.game.commondata.maintask.MainTaskConstant;
import com.motu.monstercity.server.game.commondata.rank.RankConstant;
import com.motu.monstercity.server.game.commondata.rank.RankReward;
import com.motu.monstercity.server.game.commondata.shop.Shop;
import com.motu.monstercity.server.game.commondata.shop.ShopConstant;
import com.motu.monstercity.server.game.commondata.skill.SkillConstant;
import com.motu.monstercity.server.game.commondata.union.UnionScuffleGift;
import com.motu.monstercity.server.game.commondata.union.UnionScufflePass;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.log.MotuLogManager;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.monstercity.server.game.verticle.MainVerticle;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.model.EntityManager;
import com.motu.vertx.module.utility.mysql.MysqlClient;
import com.motu.vertx.module.utility.mysql.MysqlTool;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.toolset.ErrorWord;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.Future;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.sync.Sync;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

public class UnionScuffleManager extends UnionScuffleUserData {
    private static Logger logger = LoggerFactory.getLogger(UnionScuffleManager.class);

    public static long matchBattle(UserInfo userInfo, long unionId) {
        int memberCount = UnionManager.getUnionMemberNum(unionId);
        if (memberCount < AllParam.UNION_SCUFFLE_MEMBER_LIMIT) {
            return 0;
        }
        int serverGroup = ServerManager.getWarZoneId(userInfo.getServerId());
        int myRank = RankManager.getMyRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, serverGroup, unionId, "0");
        if (myRank <= 0) { // 未入榜
            long rankCount = RankManager.getRankLength(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, serverGroup, "0");
            if (rankCount < 2) { // 战斗排行榜为空，则从收益榜中匹配
                return matchFromUnionRank(userInfo, unionId, false);
            }
            // 从最后10名中随机出来
            int minRank = (int) (rankCount + AllParam.UNION_SCUFFLE_MATCH_RANGE[0]);
            int maxRank = (int) rankCount;
            minRank = Math.max(minRank, 1);
            long randomUnionId = matchFromBattleRank(userInfo, unionId, minRank - 1, maxRank, false);
            if (randomUnionId > 0) {
                return randomUnionId;
            }
        } else {
            long rankCount = RankManager.getRankLength(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, serverGroup, "0");
            if (rankCount <= 2) { // 排行榜只有自己一个联盟，则继续从收益榜中匹配
                return matchFromUnionRank(userInfo, unionId, false);
            }
            int minRank = myRank + AllParam.UNION_SCUFFLE_MATCH_RANGE[0];
            int maxRank = myRank + AllParam.UNION_SCUFFLE_MATCH_RANGE[1];
            minRank = Math.max(minRank, 1);
            maxRank = Math.min(maxRank, (int) rankCount);
            long randomUnionId = matchFromBattleRank(userInfo, unionId, minRank - 1, maxRank, false);
            if (randomUnionId > 0) {
                return randomUnionId;
            }
        }
        return matchFromUnionRank(userInfo, unionId, false);
    }

    public static long matchFromBattleRank(UserInfo userInfo, long unionId, int minRank, int maxRank, boolean retry) {
        int serverGroup = ServerManager.getWarZoneId(userInfo.getServerId());
        JsonArray rankList = RankManager.getRankIdListByIndex(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, serverGroup, "0", minRank, maxRank);
        List<Long> unionIdList = new ArrayList<>();
        for (int i = 0; i < rankList.size(); i++) {
            long unionIdTmp = Long.parseLong(rankList.getString(i));
            if (unionIdTmp == unionId) {
                continue;
            }
            unionIdList.add(unionIdTmp);
        }
        if (!unionIdList.isEmpty()) {
            ConcurrentHashMap<Long, Long> cdUnionMap = getCdUnionMap(userInfo.getId());
            unionIdList.removeAll(cdUnionMap.keySet());
            if (unionIdList.isEmpty()) { // 如果匹配失败，则清除匹配状态重新匹配一次，再匹配不到，则返回0
                if (!retry) {
                    clearMatchStatus(userInfo.getId());
                    return matchFromBattleRank(userInfo, unionId, minRank, maxRank, true);
                }
                return 0;
            }
            Collections.shuffle(unionIdList);
            return unionIdList.get(0);
        }
        return 0;
    }

    public static ConcurrentHashMap<Long, Long> getCdUnionMap(long userId) {
        List<UserUnionScuffleWeek> userUnionScuffleList = getUserUnionScuffleList(userId);
        ConcurrentHashMap<Long, Long> cdUnionMap = new ConcurrentHashMap<>();
        long curTime = TimeUtils.getCurTime();
        for (UserUnionScuffleWeek userUnionScuffle : userUnionScuffleList) {
            if (userUnionScuffle.getMatchCdTime() > curTime) {
                cdUnionMap.put(userUnionScuffle.getEnemyUnionId(), userUnionScuffle.getMatchCdTime());
            }
        }
        return cdUnionMap;
    }

    public static void clearMatchStatus(long userId) {
//        EntityManager.delEntity(UserUnionScuffleMatch.class, userId);
//        JsonArray userUnionScuffleList = EntityManager.getEntityKeyList(UserUnionScuffle.class, userId);
//        for (int i = 0; i < userUnionScuffleList.size(); i++) {
//            String listKey = userUnionScuffleList.getString(i);
//            EntityManager.delEntity(UserUnionScuffleMember.class, listKey);
//        }
        EntityManager.delEntity(UserUnionScuffleWeek.class, userId);
//        String listKey = EntityManager.getFieldJoinString(userId, actId);
//        EntityManager.getEntity(UserUnionScuffle.class, listKey);
    }

    public static void resetUnionScuffle(UserUnionScuffleWeek userUnionScuffle) {
//        long actId = userUnionScuffle.getActId();
        long userId = userUnionScuffle.getUserId();

        userUnionScuffle.resetBattle();
        String listKey = EntityManager.getFieldJoinString(userUnionScuffle.getUserId(), userUnionScuffle.getEnemyUnionId());
        JsonArray enemyMemberList = EntityManager.getEntityKeyList(UserUnionScuffleMemberWeek.class, listKey);
        for (int i = 0; i < enemyMemberList.size(); i++) {
            long memberId = Long.parseLong(enemyMemberList.getString(i));
            String enemyPartnerListKey = EntityManager.getFieldJoinString(userId, memberId);
            EntityManager.delEntity(UserUnionScufflePartnerWeek.class, enemyPartnerListKey);
        }
        EntityManager.delEntity(UserUnionScuffleMemberWeek.class, listKey);
    }

    public static long matchFromUnionRank(UserInfo userInfo, long unionId, boolean retry) {
        long randomUnionId = matchFromUnionRank(userInfo, unionId);
        if (randomUnionId == 0 && !retry) {
            clearMatchStatus(userInfo.getId());
            randomUnionId = matchFromUnionRank(userInfo, unionId, true);
        }
        return randomUnionId;
    }

    // 从收益榜中匹配
    public static long matchFromUnionRank(UserInfo userInfo, long unionId) {
        int serverGroup = ServerManager.getWarZoneId(userInfo.getServerId());
        int myRank = RankManager.getMyRank(RankConstant.CROSS_RANK_UNION, serverGroup, unionId, "0");
        long rankCount = RankManager.getRankLength(RankConstant.CROSS_RANK_UNION, serverGroup, "0");
        ConcurrentHashMap<Long, Long> cdUnionMap = getCdUnionMap(userInfo.getId());
        int retry = 0;
        while (retry < 10) {
            int minRank, maxRank;
            if (rankCount < 5) {
                minRank = 1;
                maxRank = (int) rankCount;
            } else if (myRank <= 5) { // 前5名只向后匹配
                minRank = myRank + AllParam.UNION_SCUFFLE_MATCH_RANGE[1] * retry + 1;
                maxRank = myRank + AllParam.UNION_SCUFFLE_MATCH_RANGE[1] * (retry + 1);
                maxRank = Math.toIntExact(Math.min(rankCount, maxRank));
                if (minRank > rankCount) {
                    break;
                }
            } else { // 5名后只考虑向前匹配
                minRank = myRank + AllParam.UNION_SCUFFLE_MATCH_RANGE[0] * (retry + 1);
                maxRank = myRank + AllParam.UNION_SCUFFLE_MATCH_RANGE[0] * retry - 1;
                minRank = Math.max(minRank, 1);
                if (maxRank < 1) {
                    break;
                }
            }
            JsonArray rankList = RankManager.getRankIdListByIndex(RankConstant.CROSS_RANK_UNION, serverGroup, "0", minRank - 1, maxRank);
            List<Long> unionIdList = new ArrayList<>();
            for (int i = 0; i < rankList.size(); i++) {
                long unionIdTmp = Long.parseLong(rankList.getString(i));
                if (unionIdTmp == unionId) {
                    continue;
                }
                unionIdList.add(unionIdTmp);
            }
            if (!unionIdList.isEmpty()) {
                unionIdList.removeAll(cdUnionMap.keySet());

                if (!unionIdList.isEmpty()) {
                    Collections.shuffle(unionIdList); // 乱序排序
                    for (Long unionIdTmp : unionIdList) {
                        int unionMemberCount = UnionManager.getUnionMemberNum(unionIdTmp);
                        if (unionMemberCount >= AllParam.UNION_SCUFFLE_MEMBER_LIMIT) { // 只要有一个联盟满足要求就返回
                            return unionIdTmp;
                        }
                    }
                }
                // 如果向前取到第1名，或向后取到最后一名了，则不再继续
                if ((minRank <= 1 && myRank > 5) || (maxRank >=rankCount && myRank <= 5)) {
                    break;
                }
            } else {
                break;
            }
            if (rankCount < 5) {
                break;
            }
            retry++;
        }
        return 0;
    }

    public static UserUnionScuffleWeek createUnionBattle( UserInfo userInfo, long enemyUnionId, int matchType) {
        UserUnionScuffleWeek userUnionScuffle = getUserUnionScuffle(userInfo.getId(), enemyUnionId);
        boolean update = false;
        if (userUnionScuffle == null) {
            userUnionScuffle = new UserUnionScuffleWeek(userInfo.getId(), enemyUnionId);
        } else {
            userUnionScuffle.resetBattle();
            update = true;
        }

        long userId = userInfo.getId();
        UserPower userPower = GameUser.getUserPower(userId);
//        long initPower = GameUser.countTotalPowerModule(userId, userPower, SkillConstant.EFFECT_TYPE_4, SkillConstant.EFFECT_TYPE_61);
        long initPower = createPartnerInfo(userId, userId, userPower);
        long initPhp = (long) (initPower * 2.5);
        userUnionScuffle.putInitPower(initPower);
        userUnionScuffle.putInitHp(initPhp);
        userUnionScuffle.putCurHp(initPhp);
        userUnionScuffle.putMatchType(matchType);
        userUnionScuffle.putEnergy(AllParam.UNION_SCUFFLE_INIT_ENERGY);
        if (matchType == UserUnionScuffle.MATCH_TYPE_RANDOM) {
            userUnionScuffle.putMatchCdTime(TimeUtils.getCurTime() + AllParam.UNION_SCUFFLE_MATCH_CD_TIME);
        }
        if (update) {
            userUnionScuffle.update();
        } else {
            userUnionScuffle.doCreate();
        }
//        ProtoDataUtils.updatePBUserData(pbUserData, userUnionScuffle, true);

        long battleId = userUnionScuffle.getId();
        List<UnionMember> enemyMemberList = UnionManager.getUnionMemberList(enemyUnionId);
        for (UnionMember unionMember : enemyMemberList) {
            UserPower enemyPowerInfo = GameUser.getUserPower(unionMember.getUserId());
//            UserInfo enemyInfo = GameUser.getUserInfo(unionMember.getUserId());
            UserUnionScuffleMemberWeek member = getUserUnionScuffleMember(userId, enemyUnionId, unionMember.getUserId());
//            long enemyPower = GameUser.countTotalPowerModule(unionMember.getUserId(), enemyPowerInfo, SkillConstant.EFFECT_TYPE_4, SkillConstant.EFFECT_TYPE_61);
//            JsonArray partnerList = getPartnerList(unionMember.getUserId());
            long enemyPower = createPartnerInfo(userId, unionMember.getUserId(), enemyPowerInfo);
            UserInfo enemyMember = GameUser.getUserInfo(unionMember.getUserId());
            if (member == null) {
                member = new UserUnionScuffleMemberWeek(userId, enemyUnionId, unionMember.getUserId(), enemyPower);
                if (enemyMember != null) {
                    member.setUserInfo(enemyMember);
                }
//                member.putPartnerList(partnerList.toString());
                member.doCreate();
            } else {
                member.putPower(enemyPower);
                if (enemyMember != null) {
                    member.setUserInfo(enemyMember);
                }
//                member.putPartnerList(partnerList.toString());
                member.update();
            }
        }
        return userUnionScuffle;
    }

    public static void updateMemberInfo(Common.PBUserData.Builder pbUserData, UserUnionScuffleMemberWeek member, UserUnionScuffleWeek scuffle) {
        Common.PBUnionInfoData.Builder unionBuilder = pbUserData.getUnionBuilder();
        Common.PBUserUnionScuffleMember.Builder memberBuilder = takeMemberInfo(member, scuffle);
        unionBuilder.addEnemyMemberList(memberBuilder.build());
    }

    public static Common.PBUserUnionScuffleMember.Builder takeMemberInfo(UserUnionScuffleMemberWeek member, UserUnionScuffleWeek scuffle) {
        Common.PBUserUnionScuffleMember.Builder memberBuilder = member.takeInitBuilder();
        long myPower = countPower(scuffle);
        if (myPower > member.getPower()) {
            int score = countScore(myPower, member.getPower());
            memberBuilder.setScore(score);
        }
        return memberBuilder;
    }

    public static long createPartnerInfo(long userId, long memberId, UserPower userPower) {
        List<UserPartner> userPartnerList = PartnerManager.getUserPartnerList(memberId);
        long totalPower = 0;
        for (UserPartner userPartner : userPartnerList) {
            UserUnionScufflePartnerWeek userUnionScufflePartner = getUserUnionScufflePartner(userId, memberId, userPartner.getPartnerId());
            int skillAdd = SkillManager.getSkillMoudleAdd(memberId, SkillConstant.EFFECT_TYPE_61, userPartner.getCharacterType());// 干员技能加成,秘书技能加成
            int skillAdd2 = SkillManager.getSkillMoudleAdd(userId, SkillConstant.EFFECT_TYPE_4, userPartner.getCharacterType());// 干员技能加成,秘书技能加成
            long power = GameUser.countPowerByPartner(userId, userPartner.getPartnerId(), userPartner, userPower, skillAdd + skillAdd2);
            totalPower += power;
            if (userUnionScufflePartner == null) {
                userUnionScufflePartner = new UserUnionScufflePartnerWeek(userId, userPartner);
                userUnionScufflePartner.putTotalPower(power);
                userUnionScufflePartner.doCreate();
            } else {
                userUnionScufflePartner.initData(userPartner);
                userUnionScufflePartner.putTotalPower(power);
                userUnionScufflePartner.update();
            }
        }
        return totalPower;
    }

    public static JsonArray getPartnerList(long userId) {
        List<UserPartner> partnerList = PartnerManager.getUserPartnerList(userId);
        JsonArray arrayList = new JsonArray();
        partnerList.stream().map(UserPartner::getPartnerId).forEach(arrayList::add);
        return arrayList;
    }

    public static List<UserUnionScuffleMemberWeek> refreshMemberList(UserUnionScuffleWeek userUnionScuffle) { // 随机刷新挑战成员
        long userId = userUnionScuffle.getUserId();
        long enemyUnionId = userUnionScuffle.getEnemyUnionId();
        List<UserUnionScuffleMemberWeek> userUnionScuffleMemberList = getUserUnionScuffleMemberList(userId, enemyUnionId);
        List<UserUnionScuffleMemberWeek> result = new ArrayList<>();
        // 剔除已打败的成员
        JsonArray defeatedArray = userUnionScuffle.getDefeatedMembersArray();
        JsonArray failedMembersArray = userUnionScuffle.getFailedMembersArray();
        JsonArray matchedMemberArray = new JsonArray();
        matchedMemberArray.addAll(defeatedArray).addAll(failedMembersArray);
        List<UserUnionScuffleMemberWeek> matchList = new ArrayList<>(userUnionScuffleMemberList.stream().filter(m -> !Tool.isInList(matchedMemberArray, m.getMemberId())).toList());
        if (matchList.isEmpty()) {
            return result;
        }
        // 一开始按成员实力从大到小排序
        matchList.sort(Comparator.comparingLong(UserUnionScuffleMemberWeek::getPower).reversed());
        int groupSize = matchList.size() / 3;
        List<List<UserUnionScuffleMemberWeek>> groupList = new ArrayList<>();
        for (int i = 0; i < 3; i++) { // 初始化3个空列表
            groupList.add(new ArrayList<>());
        }
        if (groupSize > 0) {
            // 3个分组分别添加groupSize个成员，也就是把成员平均分在3个战力分区，最后剩余的成员按成员实力从小到大分配到战力最小的分区
            // 也就是说，按实力分成A、B、C分区，假如有10个成员，就是3个A分区、3个B分区、3个C分区，最后剩一个给C，剩2个分给C和B
            for (int i = 0; i < 3; i++) {
                List<UserUnionScuffleMemberWeek> group = groupList.get(2 - i);
                for (int j = 0; j < groupSize; j++) {
                    group.add(matchList.removeFirst());
                }
            }
        }
        int rest = matchList.size(); // 剩余的成员
        if (rest > 0) {
            // 剩余的成员按成员实力从小到大排序
            matchList.reversed();
            for (int i = 0; i < rest; i++) {
                groupList.get(i).add(matchList.removeFirst());
            }
        }
        JsonArray chooseList = new JsonArray();
        for (int i = 0; i < groupList.size(); i++) {
            List<UserUnionScuffleMemberWeek> group = groupList.get(i);
            if (!group.isEmpty()) {
                int randomIndex = Tool.getIntRandom(group.size());
                UserUnionScuffleMemberWeek member = group.get(randomIndex);
                result.add(member);
//                ProtoDataUtils.updatePBUserData(pbUserData, member, true);
                chooseList.add(member.getMemberId());
            }
        }
        userUnionScuffle.putChooseList(chooseList.toString());
        userUnionScuffle.update();
        return result;
    }

    /**
     * 计算当前战力
     */
    public static long countPower(UserUnionScuffleWeek userUnionScuffle) {
        int chooseBuff = userUnionScuffle.getAddPerType();
        if (chooseBuff <= 0) {
            return userUnionScuffle.getInitPower();
        }
        int addPer = getAddPerType(chooseBuff);
        long initEnergy = AllParam.UNION_SCUFFLE_INIT_ENERGY;
        long curEnergy = userUnionScuffle.getEnergy();
        long subEnergy = initEnergy - curEnergy;
        long subPer = 0;
        if (subEnergy > 0) {
            subPer = subEnergy / AllParam.UNION_SCUFFLE_ENERGY_PER;
        }
        return (userUnionScuffle.getInitPower() * (10000 + addPer) / 10000) * (100 - subPer) / 100;
    }

    public static long getAddPerPower(UserUnionScuffleWeek userUnionScuffle, long power) {
        int chooseBuff = userUnionScuffle.getAddPerType();
        if (chooseBuff <= 0) {
            chooseBuff = 1;
        }
        long subPer = 0;
        long initEnergy = AllParam.UNION_SCUFFLE_INIT_ENERGY;
        long curEnergy = userUnionScuffle.getEnergy();
        long subEnergy = initEnergy - curEnergy;
        if (subEnergy > 0) {
            subPer = subEnergy / AllParam.UNION_SCUFFLE_ENERGY_PER;
        }
        int addPer = getAddPerType(chooseBuff);
        return (power* (10000 + addPer) / 10000) * (100 - subPer) / 100;
    }

    public static int getAddPerType(int type) {
        return AllParam.UNION_SCUFFLE_ADD_PER[(type - 1) * 2];
    }

    public static boolean fight(UserUnionScuffleWeek userUnionScuffle, UserUnionScuffleMemberWeek member, CsGameUnionscuffle.CSGameUnionscuffleFightResponse.Builder resBuild) {
        long curPower = countPower(userUnionScuffle);
        // 生成每局战斗数据
        CsGameUnionscuffle.PBUnionScuffleFightData.Builder fightBuilder = CsGameUnionscuffle.PBUnionScuffleFightData.newBuilder();
        fightBuilder.setMyPower(curPower);
        fightBuilder.setMyHp(userUnionScuffle.getCurHp());
        fightBuilder.setMember(member.takeInitBuilder());
        fightBuilder.setMyEnergy(userUnionScuffle.getEnergy());
        List<UserUnionScufflePartnerWeek> partnerList = getUserUnionScufflePartnerList(userUnionScuffle.getUserId(), member.getMemberId());
//        System.out.println("partnerList of [" + member.getMemberId() + "]:" + partnerList.size());
        for (UserUnionScufflePartnerWeek userUnionScufflePartner : partnerList) {
            fightBuilder.putPartnerList(userUnionScufflePartner.getPartnerId(), userUnionScufflePartner.takeInitBuilder().build());
        }
        List<UserUnionScufflePartnerWeek> myPartnerList = getUserUnionScufflePartnerList(userUnionScuffle.getUserId(), userUnionScuffle.getUserId());
        for (UserUnionScufflePartnerWeek userUnionScufflePartner : myPartnerList) {
            Common.PBUserUnionScufflePartner.Builder pbUserUnionScufflePartner = userUnionScufflePartner.takeInitBuilder();
            pbUserUnionScufflePartner.setTotalPower(getAddPerPower(userUnionScuffle, userUnionScufflePartner.getTotalPower()));
            fightBuilder.putMyPartnerList(userUnionScufflePartner.getPartnerId(), pbUserUnionScufflePartner.build());
        }
        boolean isWin = curPower > member.getPower();
        if (isWin) {
            long addScore = countScore(curPower, member.getPower());
            fightBuilder.setAddScore(addScore);
        }
        fightBuilder.setIsWin(isWin ? 1 : 0);
        resBuild.addFightList(fightBuilder);
        JsonArray defeatMembersArray = userUnionScuffle.getDefeatedMembersArray();
        JsonArray failedMembersArray = userUnionScuffle.getFailedMembersArray();
        if (isWin) {
            defeatMembersArray.add(member.getMemberId());
            userUnionScuffle.putDefeatedMembers(defeatMembersArray.toString());
            userUnionScuffle.addWiningStreak(1); // 战胜则累计连胜数
        } else {
            failedMembersArray.add(member.getMemberId());
            userUnionScuffle.putFailedMembers(failedMembersArray.toString());
            userUnionScuffle.putWiningStreak(0); // 战败则重置连胜数
        }

        long curHp = userUnionScuffle.getCurHp();
        curHp -= member.getPower();
        curHp = Math.max(0, curHp);
        int curEnergy = userUnionScuffle.getEnergy();
        curEnergy -= AllParam.UNION_SCUFFLE_ENERGY_COST;
        curEnergy = Math.max(0, curEnergy);
        userUnionScuffle.putEnergy(curEnergy);
        userUnionScuffle.putCurHp(curHp);
        userUnionScuffle.checkWiningStreak();
        return isWin;
    }

    public static void saveReport(UserInfo userInfo, UnionInfo unionInfo, UnionInfo enemyUnionInfo, int defeatCount, int subScore, int matchType) {
        UnionScuffleReportWeek report = new UnionScuffleReportWeek(enemyUnionInfo.getId(), userInfo, unionInfo, defeatCount, subScore, matchType);
        report.doCreate();
    }

    public static int computeScore(long myPower, long enemyPower) {
        if (myPower <= enemyPower) {
            return 0;
        }
        double factor = (double) myPower / (myPower - enemyPower);
        // 个人积分上升
        return (int) (1500 * (1 + Math.log(factor)));
    }

    public static int countScore(long myPower, long enemyPower) {
        return (int) (500 * (1 + Math.log(enemyPower) * (1 + Math.log(myPower)) / 50));
    }

    public static void subScore(UserInfo userInfo, long unionId, UserUnionScuffleWeek userUnionScuffle, UserUnionScuffleInfoWeek userUnionScuffleInfo, long myPower, long enemyPower, long enemyUnionId) {
        int serverGroup = ServerManager.getWarZoneId(userInfo.getServerId());
        if (enemyPower >= myPower) { // 如果挑战失败则判断是否在排行榜中，如果不在排行中则默认给0分上榜
//            int myRank = RankManager.getMyRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE, serverGroup, userInfo.getId(),String.valueOf(actId));
//            if (myRank <= 0) {
//                RankManager.updateRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE, serverGroup, userInfo.getId(), 0, String.valueOf(actId));
//            }
//            int myUnionRank = RankManager.getMyRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, serverGroup, unionId, String.valueOf(actId));
//            if (myUnionRank <= 0) {
//                RankManager.updateRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, serverGroup, unionId, 0, String.valueOf(actId));
//            }
            return;
        }
//        double factor = (double) myPower / (myPower - enemyPower);
        // 个人积分上升
        int addScore = countScore(myPower, enemyPower);
        userUnionScuffleInfo.addScore(addScore);
        userUnionScuffleInfo.update();
        userUnionScuffle.addSubScore(addScore);
        userUnionScuffle.update();
        RankManager.updateRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE, serverGroup, userInfo.getId(),
                userUnionScuffleInfo.getScore(), "0");
        UnionInfo unionInfo = UnionManager.getUnionInfo(unionId);
        updateUnionScore(unionInfo);
        JsonArray defeatMembersArray = userUnionScuffle.getDefeatedMembersArray();
        int defeatCount = defeatMembersArray.size();
        if (defeatCount > 3) {
            final int subScore = (int) (500 * (Math.log10(defeatCount - 2)));
//            List<UserUnionScuffleMemberWeek> memberList = getUserUnionScuffleMemberList(userInfo.getId(), enemyUnionId);
            JsonArray memberList = UnionManager.getUnionMemberIdList(enemyUnionId);
            UnionInfo enemyUnionInfo = UnionManager.getUnionInfo(enemyUnionId);
            for (int i = 0; i < memberList.size(); i++) {
                long memberId = Long.parseLong(memberList.getString(i));
                UserUnionScuffleInfoWeek memberUnionScuffleInfo = UnionScuffleUserData.getUserUnionScuffleInfo(memberId);
                if (memberUnionScuffleInfo == null) {
                    continue;
                }
                long memberScore = memberUnionScuffleInfo.getScore();
                long memberSubScore = subScore;
                if (memberSubScore > memberScore) {
                    memberSubScore = (int) memberScore;
                }
                if (memberSubScore > 0) {
                    memberScore -= memberSubScore;
                    memberUnionScuffleInfo.putScore(memberScore);
                    memberUnionScuffleInfo.update();

                    RankManager.updateRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE, serverGroup,
                            memberId, memberScore, "0");
                }
            }
            updateUnionScore(enemyUnionInfo);
            saveReport(userInfo, unionInfo, enemyUnionInfo, defeatCount, subScore, userUnionScuffle.getMatchType());
        }
    }

    public static void endBattle(Common.PBUserData.Builder pbUserData, UserInfo userInfo, UserUnionScuffleInfoWeek userUnionScuffleInfo, UserUnionScuffleWeek userUnionScuffle, long unionId) {
        userUnionScuffleInfo.putEnemyUnionId(0);
        userUnionScuffleInfo.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userUnionScuffleInfo);
//        ProtoDataUtils.updatePBUserData(pbUserData, userUnionScuffle, true);
        if (userUnionScuffle.getDefeatedMembersArray().size() >= AllParam.UNION_SCUFFLE_NOTICE_BEAT_NUM) {
            UnionScuffleManager.saveNotice(userInfo, userUnionScuffle, unionId, userUnionScuffle.getEnemyUnionId());
        }
        UnionScuffleManager.resetUnionScuffle(userUnionScuffle);
        if (userUnionScuffle.getMatchType() == UserUnionScuffle.MATCH_TYPE_RANDOM) {
            RewardManager.addReward(userInfo, ItemId.SCUFFLE_COIN, AllParam.UNION_SCUFFLE_RANDOM_COIN, pbUserData, LogType.UNION_SCUFFLE_FIGHT);
        } else {
            RewardManager.addReward(userInfo, ItemId.SCUFFLE_COIN, AllParam.UNION_SCUFFLE_TARGET_COIN, pbUserData, LogType.UNION_SCUFFLE_FIGHT);
        }
    }

    public static void updateUnionScore(UnionInfo unionInfo) {
        long unionId = unionInfo.getId();
        JsonArray memberIdArray = UnionManager.getUnionMemberIdList(unionId);
        long totalScore = 0;
        int actGroup = ServerManager.getWarZoneId(unionInfo.getServerId());
        for (int i = 0; i < memberIdArray.size(); i++) {
            long memberId = Long.parseLong(memberIdArray.getString(i));
            long memberScore = RankManager.getMyScore(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE, actGroup, memberId, "0");
            if (memberScore > 0) {
                totalScore +=  memberScore;
            }
        }
        RankManager.updateRank(RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE, actGroup, unionId, totalScore, "0");
    }

    public static void saveNotice(UserInfo attacker, UserUnionScuffleWeek scuffle, long unionId, long defendUnionId) {
        JsonArray defeatArray = scuffle.getDefeatedMembersArray();
        UnionInfo attackUnion = UnionManager.getUnionInfo(unionId);
        UnionInfo defendUnion = UnionManager.getUnionInfo(defendUnionId);
        if (attackUnion == null || defendUnion == null) {
            return;
        }
        int memberTotalCount = getMemberTotalCount(attacker.getId(), defendUnionId);
        UnionScuffleNoticeWeek notice = new UnionScuffleNoticeWeek(attacker, attackUnion, defendUnion, memberTotalCount, defeatArray.size());
//        notice.putActId(scuffle.getActId());
        notice.doCreate();
    }

    public static void clearUnionScuffleReport() {
        EntityManager.delEntity(UnionScuffleNoticeWeek.class, "");
        String sql = "SELECT DISTINCT union_id from union_scuffle_report_week;";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql, new JsonArray(), h -> {
            if (h.succeeded()) {
                JsonArray result = h.result();
                for (int i = 0; i < result.size(); i++) {
                    JsonObject item = result.getJsonObject(i);
                    long unionId = item.getLong("union_id");
                    EntityManager.delEntity(UnionScuffleReportWeek.class, unionId);
                }
            } else {
                String err = Tool.getException(h.cause());
                logger.error("clearUnionScuffleReport error:" + err);
            }
        });
    }

    public static void updateAchieve(Common.PBUserData.Builder pbUserData, UserInfo userInfo, long unionId, int num) {
        MainTaskManager.updateUserHonor(pbUserData, userInfo, MainTaskConstant.HONOR_TYPE_1001, num, true);
        MainTaskManager.updateUnionHonor(pbUserData, unionId, MainTaskConstant.HONOR_TYPE_1002, num, true);
    }

    public static void closeMatchRank() {
        logger.info("================= closeMatchRank ===================");
        ConcurrentHashMap<Integer, ServerInfo> serverList = ServerManager.getServerList();
        List<Integer> serverGroupList = new ArrayList<>();
        for (ServerInfo serverInfo : serverList.values()) {
            if (!serverInfo.isMerged() && !serverGroupList.contains(serverInfo.getWarZone())) {
                singleRankReward(serverInfo.getWarZone());
                unionRewardRank(serverInfo.getWarZone());
                serverGroupList.add(serverInfo.getWarZone());
            }
        }
        clearUnionScuffleReport();
    }

    // 乱斗排行榜个人榜结算
    public static void singleRankReward(int serverGroup) {
        try {
            logger.info("================ singleRankReward: serverGroup={} ===================", serverGroup);
            int rankId = RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE;
            String dateKey = TimeUtils.getDayStr(TimeUtils.getCurTime());
            String rankName = RankManager.getRankName(rankId, serverGroup, "0");
            JsonArray rankList = Future.await(RedisTools.getRankListByIndex(rankName, 0, 0, true));
            String newRankName = RankManager.getRankName(rankId, serverGroup, dateKey);
            logger.info("singleRankReward: serverGroup={}, rankList={}", serverGroup, rankList.size());
            for (int i = 0; i < rankList.size(); i+=2) {
                long userId = Long.parseLong(rankList.getString(i));
                double score = RankManager.getTrueScore(Double.parseDouble(rankList.getString(i + 1)));// 根据时间计算的积分
                RedisTools.addRank(newRankName, userId, score);

                UserUnionScuffleInfoWeek userUnionScuffleInfo = UnionScuffleUserData.getUserUnionScuffleInfo(userId);
                if (userUnionScuffleInfo == null || userUnionScuffleInfo.getSingleRankReward() > 0) {
                    continue;
                }
                RankReward rankReward = RankManager.getRankReward(rankId, i + 1);
                if (rankReward == null) {
                    continue;
                }
                List<RewardItem> rewardItemList = CommonUtils.takeReawrdItemFromStr(rankReward.getReward());// 奖励
                MailManager.sendSystemMailReplaceContent(userId, MailConstant.UNION_SCUFFLE_SINGLE_RANK_MAIL_TITLE,
                        MailConstant.UNION_SCUFFLE_SINGLE_RANK_MAIL_CONTENT, rewardItemList, LogType.UNION_SCUFFLE_RANK_REWARD, i + 1);
                userUnionScuffleInfo.putEnemyUnionId(0);
                userUnionScuffleInfo.putSingleRankReward(rankReward.getId());
//                sendPassReward(userUnionScuffleInfo);
                userUnionScuffleInfo.update();
            }
            RedisTools.del(rankName);
            RedisTools.expire(newRankName, TimeUtils.WEEK);
            logger.info("singleRankReward: serverGroup={} send succeed.", serverGroup);
        } catch (Exception e) {
            String err = Tool.getException(e);
            MotuLogManager.addServerCrashLog(0, err);
            logger.error("singleRankReward, serverGroup={}, error:{}", serverGroup, err);
        }
    }

    /**
     * 补发通行证奖励
     */
    public static void sendPassReward(UserUnionScuffleInfoWeek userUnionScuffleInfo) {
        int normalRewardId = userUnionScuffleInfo.getNormalPassReward();
        int highRewardId = userUnionScuffleInfo.getHighPassRewad();
        int specialRewardId = userUnionScuffleInfo.getSpecialPassReward();
        int beatNum = userUnionScuffleInfo.getBeatNum();
        List<UnionScufflePass> normalPassList = UnionScuffleUserData.getUnionScufflePassList(normalRewardId + 1);
        ConcurrentHashMap<Integer, Long> rewardMap = new ConcurrentHashMap<>();
        for (UnionScufflePass unionScufflePass : normalPassList) {
            if (unionScufflePass.getNum() > beatNum) {
                break;
            }
            RewardManager.mergeItemMap(rewardMap, RewardManager.itemsToList(unionScufflePass.getNormalReward()));
            normalRewardId = unionScufflePass.getId();
        }
        if (userUnionScuffleInfo.getBuyHigh() == UserUnionScuffleInfo.YES) {
            List<UnionScufflePass> highPassList = UnionScuffleUserData.getUnionScufflePassList(highRewardId + 1);
            for (UnionScufflePass unionScufflePass : highPassList) {
                if (unionScufflePass.getNum() > beatNum) {
                    break;
                }
                RewardManager.mergeItemMap(rewardMap, RewardManager.itemsToList(unionScufflePass.getHighReward()));
                highRewardId = unionScufflePass.getId();
            }
        }
        if (userUnionScuffleInfo.getBuySpecial() == UserUnionScuffleInfo.YES) {
            List<UnionScufflePass> specialPassList = UnionScuffleUserData.getUnionScufflePassList(specialRewardId + 1);
            for (UnionScufflePass unionScufflePass : specialPassList) {
                if (unionScufflePass.getNum() > beatNum) {
                    break;
                }
                RewardManager.mergeItemMap(rewardMap, RewardManager.itemsToList(unionScufflePass.getSpecialReward()));
                specialRewardId = unionScufflePass.getId();
            }
        }
        if (normalRewardId == userUnionScuffleInfo.getNormalPassReward() && highRewardId == userUnionScuffleInfo.getHighPassRewad() && specialRewardId == userUnionScuffleInfo.getSpecialPassReward()) {
            return;
        }
        if (normalRewardId != userUnionScuffleInfo.getNormalPassReward()) {
            userUnionScuffleInfo.putNormalPassReward(normalRewardId);
        }
        if (highRewardId != userUnionScuffleInfo.getHighPassRewad()) {
            userUnionScuffleInfo.putHighPassRewad(highRewardId);
        }
        if (specialRewardId != userUnionScuffleInfo.getSpecialPassReward()) {
            userUnionScuffleInfo.putSpecialPassReward(specialRewardId);
        }
        if (!rewardMap.isEmpty()) {
            MailManager.sendSystemMailReplaceContent(userUnionScuffleInfo.getId(), MailConstant.UNION_SCUFFLE_PASS_REWARD_TITLE,
                    MailConstant.UNION_SCUFFLE_PASS_REWARD_CONTENT, RewardManager.itemMap2RewardList(rewardMap), LogType.UNION_SCUFFLE_PASS_REISSUE_REWARD);
        }
    }

    // 乱斗排行榜联盟榜结算
    public static void unionRewardRank(int serverGroup) {
        try {
            logger.info("================ unionRewardRank: serverGroup={} ===================", serverGroup);
            int rankId = RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE;
            String dateKey = TimeUtils.getDayStr(TimeUtils.getCurTime());
            String rankName = RankManager.getRankName(rankId, serverGroup, "0");
            JsonArray rankList = Future.await(RedisTools.getRankListByIndex(rankName, 0, 0, true));
//            JsonArray rankList = RankManager.getRankIdListByIndex(rankId,  serverGroup, "0", 0, 0);
            logger.info("unionRewardRank: serverGroup={}, rankList={}", serverGroup, rankList.size());
            for (int i = 0; i < rankList.size(); i+=2) {
                long unionId = Long.parseLong(rankList.getString(i));
                UnionInfo unionInfo = UnionManager.getUnionInfo(unionId);
                if (unionInfo == null) {
                    continue;
                }
                JsonArray memberIdList = UnionManager.getUnionMemberIdList(unionId);
                for (int j = 0; j < memberIdList.size(); j++) {
                    long userId = Long.parseLong(memberIdList.getString(j));
                    UserUnionScuffleInfoWeek userUnionScuffleInfo = UnionScuffleUserData.getUserUnionScuffleInfo(userId);
                    if (userUnionScuffleInfo == null || userUnionScuffleInfo.getUnionRankReward() > 0) {
                        continue;
                    }
                    RankReward rankReward = RankManager.getRankReward(rankId, i + 1);
                    if (rankReward == null) {
                        continue;
                    }
                    List<RewardItem> rewardItemList = CommonUtils.takeReawrdItemFromStr(rankReward.getReward());
                    MailManager.sendSystemMailReplaceContent(userId, MailConstant.UNION_SCUFFLE_UNION_RANK_MAIL_TITLE,
                            MailConstant.UNION_SCUFFLE_UNION_RANK_MAIL_CONTENT, rewardItemList, LogType.UNION_SCUFFLE_RANK_REWARD, i + 1);
                    userUnionScuffleInfo.putUnionRankReward(rankReward.getId());
                    userUnionScuffleInfo.update();
                }
            }
            logger.info("unionRewardRank: serverGroup={} send succeed.", serverGroup);
        } catch (Exception e) {
            String err = Tool.getException(e);
            MotuLogManager.addServerCrashLog(0, err);
            logger.error("unionRewardRank, serverGroup={}, error:{}", serverGroup, err);
        }
    }

    public static void clearActData(Act act) {
        try {
            logger.info("=================== clearActData =========================");
            ConcurrentHashMap<Integer, ServerInfo> serverList = ServerManager.getServerList();
            List<Integer> serverGroupList = new ArrayList<>();
            for (ServerInfo serverInfo : serverList.values()) {
                if (!serverInfo.isMerged() && serverInfo.isShow()) {
                    deleteMemberData(serverInfo.getWarZone(), act.getId());
                    serverGroupList.add(serverInfo.getWarZone());
                }
            }
        } catch (Exception e) {
            String err = Tool.getException(e);
            MotuLogManager.addServerCrashLog(0, err);
            logger.error("clearActData, error:{}", err);
        }
    }

    public static void deleteMemberData(int actGroup, long actId) {
        try {
            logger.info("=================== deleteMemberData =========================");
            int rankId = RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE;
            JsonArray rankList = RankManager.getRankIdListByIndex(rankId,  actGroup, String.valueOf(actId), 0, 0);
            logger.info("unionRewardRank: actGroup={}, rankList={}", actGroup, rankList.size());
            for (int i = 0; i < rankList.size(); i++) {
                long unionId = Long.parseLong(rankList.getString(i));
                UnionInfo unionInfo = UnionManager.getUnionInfo(unionId);
                if (unionInfo == null) {
                    continue;
                }
//                String reportKey = EntityManager.getFieldJoinString(unionId,  actId);
                EntityManager.delEntity(UnionScuffleReportWeek.class, unionId);
                clearUnionScuffleReport();
            }
            int rankId2 = RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE;
            JsonArray singleRankList = RankManager.getRankIdListByIndex(rankId2,  actGroup, String.valueOf(actId), 0, 0);
            logger.info("unionRewardRank: actGroup={}, singleRankList={}", actGroup, singleRankList.size());
            // 删除玩家的乱斗数据（如果有匹配未完成的战斗）
//            for (int i = 0; i < singleRankList.size(); i++) {
//                long userId = Long.parseLong(singleRankList.getString(i));
//                deleteMatchData(userId, actId);
//            }
        } catch (Exception e) {
            String err = Tool.getException(e);
            MotuLogManager.addServerCrashLog(0, err);
            logger.error("deleteMemberData, error:{}", err);
        }
    }


    public static void resetUnionScuffleInfo(long userId) {
        try {
            UserUnionScuffleInfoWeek userUnionScuffleInfo = UnionScuffleUserData.getUserUnionScuffleInfo(userId);
            sendPassReward(userUnionScuffleInfo);
            deleteMatchData(userId);
            userUnionScuffleInfo.delete();
        } catch (Exception e) {
            logger.error("resetUnionScuffleInfo, userId={}, error:{}", userId, Tool.getException(e));
        }
    }

    private static void deleteMatchData(long userId) {
//        EntityManager.delOneEntity(UserUnionScuffleInfoWeek.class, userId);
//        String scuffleListKey = EntityManager.getFieldJoinString(userId, actId);
        JsonArray memberKeyList = EntityManager.getEntityKeyList(UserUnionScuffleWeek.class, userId);
        for (int j = 0; j < memberKeyList.size(); j++) {
            long enemyUnionId = Long.parseLong(memberKeyList.getString(j));
            String scuffleMemberListKey = EntityManager.getFieldJoinString(userId, enemyUnionId);
            JsonArray memberList = EntityManager.getEntityKeyList(UserUnionScuffleMember.class, scuffleMemberListKey);
            for (int k = 0; k < memberList.size(); k++) {
                long memberId = Long.parseLong(memberList.getString(k));
                EntityManager.delEntity(UserUnionScufflePartnerWeek.class, EntityManager.getFieldJoinString(userId, memberId));
            }
            EntityManager.delEntity(UserUnionScuffleMember.class, scuffleMemberListKey);
        }
        EntityManager.delEntity(UserUnionScuffleWeek.class, userId);
        EntityManager.delEntity(UserUnionScuffleGiftWeek.class, userId);
        EntityManager.delEntity(UserUnionScuffleShopWeek.class, userId);
    }

    public static ErrorWord checkUserUnionScuffleGift(UserInfo userInfo, IapGift iapGift) {
//        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_UNION_SCUFFLE, userInfo.getServerId());
//        if (act == null || !act.isStart(userInfo.getServerId())) {
//            return ErrorWord.WRONG_STATUS;
//        }
        if (!isDuringGame()) {
            return ErrorWord.WRONG_STATUS;
        }
        if (iapGift.getType() != IapGift.TYPE_UNION_SCUFFLE_GIFT) {
            return ErrorWord.BAD_PARAM;
        }
        if (!FunctionManager.isFunctionClientOpen(FunctionManager.FUNCTION_ID_UNION_SCUFFLE, userInfo.getServerId())) {
            return ErrorWord.MODULE_LOCKED;
        }
        UnionScuffleGift unionScuffleGift = getUnionScuffleGiftByIapId(iapGift.getId());
        if (unionScuffleGift == null) {
            return ErrorWord.NOT_DATA;
        }
        long userId = userInfo.getId();
        UserUnionScuffleGiftWeek userUnionScuffleGift = getUserUnionScuffleGift(userId, unionScuffleGift.getId());
        if (userUnionScuffleGift != null && userUnionScuffleGift.getBuyNum() >= unionScuffleGift.getLimitCount()) {
            return ErrorWord.ALREADY_MAX;
        }
        return null;
    }

    public static void updateUserUnionScuffleGift(Common.PBUserData.Builder pbUserData, UserInfo userInfo, IapGift iapGift) {
        if (iapGift.getType() != IapGift.TYPE_UNION_SCUFFLE_GIFT) {
            return;
        }
        if (!FunctionManager.isFunctionClientOpen(FunctionManager.FUNCTION_ID_UNION_SCUFFLE, userInfo.getServerId())) {
            return;
        }
//        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_UNION_SCUFFLE, userInfo.getServerId());
//        if (act == null || !act.isStart(userInfo.getServerId())) {
//            return;
//        }
        if (!isDuringGame()) {
            return;
        }
        UnionScuffleGift unionScuffleGift = getUnionScuffleGiftByIapId(iapGift.getId());
        if (unionScuffleGift == null) {
            return;
        }
        long userId = userInfo.getId();
        UserUnionScuffleGiftWeek userUnionScuffleGift = getUserUnionScuffleGift(userId, unionScuffleGift.getId());
        if (null == userUnionScuffleGift) {
            userUnionScuffleGift = new UserUnionScuffleGiftWeek(userId, unionScuffleGift.getId());
            userUnionScuffleGift.putBuyNum(1);
            userUnionScuffleGift.doCreate();
        } else {
            userUnionScuffleGift.addBuyNum(1);
            userUnionScuffleGift.update();
        }
        ProtoDataUtils.updatePBUserData(pbUserData, userUnionScuffleGift);
    }

    public static ErrorWord checkBuyPassGift(UserInfo userInfo, IapGift iapGift) {
        if (iapGift.getType() == IapGift.TYPE_UNION_SCUFFLE_PASS) {
            if (!FunctionManager.isFunctionClientOpen(FunctionManager.FUNCTION_ID_UNION_SCUFFLE, userInfo.getServerId())) {
                return ErrorWord.MODULE_LOCKED;
            }
//            Act act = ActManager.getActByType(ActConstant.ACT_TYPE_UNION_SCUFFLE, userInfo.getServerId());
//            if (act == null || !act.isStart(userInfo.getServerId())) {
//                return ErrorWord.NOT_DATA;
//            }
            if (!isDuringGame()) {
                return ErrorWord.NOT_DATA;
            }
            int iapGiftId = iapGift.getId();
            UserUnionScuffleInfoWeek userUnionScuffleInfo = getUserUnionScuffleInfo(userInfo.getId());
            if (iapGiftId == IapGift.ID_UNION_SCUFFLE_PASS_HIGH) {
                if (userUnionScuffleInfo.getBuyHigh() == 1) {
                    return ErrorWord.REPEATED_OPERATION;
                }
            } else if (iapGiftId == IapGift.ID_UNION_SCUFFLE_PASS_SPECIAL) {
                if (userUnionScuffleInfo.getBuySpecial() == 1) {
                    return ErrorWord.REPEATED_OPERATION;
                }
            } else {
                return ErrorWord.NOT_DATA_1;
            }
            return null;
        }
        return ErrorWord.INVALID_OPERATION;
    }

    public static void updatePassGift(Common.PBUserData.Builder pbUserData, UserInfo userInfo, IapGift iapGift) {
        if (iapGift.getType() == IapGift.TYPE_UNION_SCUFFLE_PASS) {
            if (!FunctionManager.isFunctionClientOpen(FunctionManager.FUNCTION_ID_UNION_SCUFFLE, userInfo.getServerId())) {
                return;
            }
            if (!isDuringGame()) {
                return;
            }
//            Act act = ActManager.getActByType(ActConstant.ACT_TYPE_UNION_SCUFFLE, userInfo.getServerId());
//            if (act == null || !act.isStart(userInfo.getServerId())) {
//                return;
//            }
            int iapGiftId = iapGift.getId();
            boolean update = true;
            UserUnionScuffleInfoWeek userUnionScuffleInfo = getUserUnionScuffleInfo(userInfo.getId());
            if (iapGiftId == IapGift.ID_UNION_SCUFFLE_PASS_HIGH) {
                userUnionScuffleInfo.putBuyHigh((byte) 1);
            } else if (iapGiftId == IapGift.ID_UNION_SCUFFLE_PASS_SPECIAL) {
                userUnionScuffleInfo.putBuySpecial((byte) 1);
            } else {
                update = false;
            }
            if (update) {
                userUnionScuffleInfo.update();
                ProtoDataUtils.updatePBUserData(pbUserData, userUnionScuffleInfo);
            }
        }
    }

    /**
     * 是否可在商店购买宝箱
     * 1. 活动期间
     * @return
     */
    public static boolean isShopBuyBox(UserInfo userInfo, Shop shop){
        long userId = userInfo.getId();
        UserUnion userUnion = UnionManager.getUserUnion(userId);
        long unionId = userUnion.getUnionId();
        if (unionId == 0) {
            return false;//没有联盟不可购买
        }
//        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_UNION_SCUFFLE, userInfo.getServerId());
//        if (act == null || !act.isStart(userInfo.getServerId())) {
//            return false; // 活动未开启不能购买
//        }
        return isDuringGame();
    }

    public static long getScuffleScore(UserInfo userInfo) {
//        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_UNION_SCUFFLE, userInfo.getServerId());
//        if (act == null || !act.isStart(userInfo.getServerId())) {
//            return 0;
//        }
        if (!isDuringGame()) {
            return 0;
        }
        UserUnionScuffleInfoWeek userUnionScuffleInfo = getUserUnionScuffleInfo(userInfo.getId());
        return userUnionScuffleInfo.getScore();
    }

    public static long getStartTime() {
        return TimeUtils.getWeekOneTime(AllParam.UNION_SCUFFLE_START_DAY, "00:00:00");
    }
    public static long getCloseTime() {
        return TimeUtils.getWeekOneTime(AllParam.UNION_SCUFFLE_CLOSE_DAY, AllParam.UNION_SCUFFLE_CLOSE_TIME);
    }
    public static long getResetTime() {
        return TimeUtils.getWeekOneTime(AllParam.UNION_SCUFFLE_END_DAY, AllParam.UNION_SCUFFLE_END_TIME);
    }

    public static boolean isDuringGame() {
        long startTime = getStartTime();
        long closeTime = getCloseTime();
        long time = TimeUtils.getCurTime();
        return time >= startTime && time <= closeTime;
    }

    public static boolean isRewardTime() {
        long closeTime = getCloseTime();
        long resetTime = getResetTime();
        long time = TimeUtils.getCurTime();
        if (resetTime < time) {
            resetTime += TimeUtils.WEEK;
        }
        return time >= closeTime && time < resetTime;
    }

    public static boolean checkShopLimit(UserUnionScuffleShopWeek userUnionScuffleShop, Shop shop,  int num) {
        if (shop.getLimitType() == ShopConstant.SHOP_LIMIT_TYPE_1) {
            return userUnionScuffleShop.getDayBuyNum() + num <= shop.getLimitNum();
        } else {
            return userUnionScuffleShop.getBuyNum() + num <= shop.getLimitNum();
        }
    }

    public static int getMemberCount(long userId, long actId, long enemyUnionId) {
        String listKey = EntityManager.getFieldJoinString(userId, actId, enemyUnionId);
        return (int) EntityManager.getEntityCount(UserUnionScuffleMember.class, listKey);
    }
    public static int getMemberCount(long userId, long enemyUnionId) {
        String listKey = EntityManager.getFieldJoinString(userId, enemyUnionId);
        return (int) EntityManager.getEntityCount(UserUnionScuffleMemberWeek.class, listKey);
    }

    public static void loadTimeInfo(Common.PBUserData.Builder pbUserData) {
        long startTime = getStartTime();
        long closeTime = getCloseTime();
        long resetTime = getResetTime();
        long curTime = TimeUtils.getCurTime();
        if (resetTime < curTime) {
            resetTime += TimeUtils.WEEK;
        }
        Common.PBUnionScuffleTimeInfo.Builder timeInfo = Common.PBUnionScuffleTimeInfo.newBuilder();
        timeInfo.setStartTime(startTime);
        timeInfo.setEndTime(closeTime);
        timeInfo.setResetTime(resetTime);
        pbUserData.getActBuilder().setUnionScuffleTimeInfo(timeInfo);
    }

    public static void clearRankData() {
        logger.info("================= clearRankData =================");
        try {
            ConcurrentHashMap<Integer, ServerInfo> serverList = ServerManager.getServerList();
            List<Integer> serverGroupList = new ArrayList<>();
            for (ServerInfo serverInfo : serverList.values()) {
                if (!serverInfo.isMerged() && !serverGroupList.contains(serverInfo.getWarZone())) {
                    clearSingleRankData(serverInfo.getWarZone());
                    clearUnionRankData(serverInfo.getWarZone());
                    serverGroupList.add(serverInfo.getWarZone());
                }
            }
            clearUserData();
        } catch (Exception e) {
            String errMsg = Tool.getException(e);
            logger.error("clearRankData error:" + errMsg);
        }
    }

    public static void clearSingleRankData(int serverGroup) {
        logger.info("================= clearSingleRankData =================");
        try {
            int rankId = RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE_SINGLE;
            String dateKey = TimeUtils.getDayStr(TimeUtils.getCurTime());
            String rankName = RankManager.getRankName(rankId, serverGroup, "0");
            JsonArray rankList = Future.await(RedisTools.getRankListByIndex(rankName, 0, 0, true));
            String newRankName = RankManager.getRankName(rankId, serverGroup, dateKey);
            logger.info("singleRankReward: serverGroup={}, rankList={}", serverGroup, rankList.size());
            for (int i = 0; i < rankList.size(); i+=2) {
                long userId = Long.parseLong(rankList.getString(i));
                double score = RankManager.getTrueScore(Double.parseDouble(rankList.getString(i + 1)));// 根据时间计算的积分
                RedisTools.addRank(newRankName, userId, score);
            }
            RedisTools.del(rankName);
            RedisTools.expire(newRankName, TimeUtils.WEEK);
            logger.info("singleRankReward: serverGroup={} send succeed.", serverGroup);
        } catch (Exception e) {
            String errMsg = Tool.getException(e);
            logger.error("clearSingleRankData error:" + errMsg);
        }
    }

    public static void clearUnionRankData(int serverGroup) {
        logger.info("================= clearUnionRankData =================");
        try {
            int rankId = RankConstant.ACTIVITY_CROSS_RANK_UNION_SCUFFLE;
            String dateKey = TimeUtils.getDayStr(TimeUtils.getCurTime());
            String rankName = RankManager.getRankName(rankId, serverGroup, "0");
            JsonArray rankList = Future.await(RedisTools.getRankListByIndex(rankName, 0, 0, true));
            String newRankName = RankManager.getRankName(rankId, serverGroup, dateKey);
//            JsonArray rankList = RankManager.getRankIdListByIndex(rankId,  serverGroup, "0", 0, 0);
            logger.info("clearUnionRankData: serverGroup={}, rankList={}", serverGroup, rankList.size());
            for (int i = 0; i < rankList.size(); i+=2) {
                long unionId = Long.parseLong(rankList.getString(i));
                UnionInfo unionInfo = UnionManager.getUnionInfo(unionId);
                if (unionInfo == null) {
                    continue;
                }
                double score = RankManager.getTrueScore(Double.parseDouble(rankList.getString(i + 1)));// 根据时间计算的积分
                RedisTools.addRank(newRankName, unionId, score);
            }
            RedisTools.del(rankName);
            RedisTools.expire(newRankName, TimeUtils.WEEK);
        } catch (Exception e) {
            String errMsg = Tool.getException(e);
            logger.error("clearUnionRankData error:" + errMsg);
        }
    }

    public static void clearUserData() {
        logger.info("================= clearUserData =================");
        try {
            String sql = "select id from user_union_scuffle_info_week where week_reset_time < ?";
            JsonArray params = new JsonArray();
            params.add(TimeUtils.getWeekOneTime(1, 0));
            JsonArray userIdList = Future.await(MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql, params));
            logger.info("clearUserData size: " + userIdList.size());
            for (int i = 0; i < userIdList.size(); i++) {
                JsonObject item = userIdList.getJsonObject(i);
                long userId = Long.parseLong(item.getString("id"));
                resetUnionScuffleInfo(userId);
            }
        } catch (Exception e) {
            String errMsg = Tool.getException(e);
            logger.error("clearUserData error:" + errMsg);
        }
    }

}
